package cn.hfjava.kz.controller;

import cn.dev33.satoken.util.SaResult;
import cn.hfjava.kz.common.UpdateGroup;
import cn.hfjava.kz.entity.dto.ApplicationFormDTO;
import cn.hfjava.kz.entity.dto.ApplicationQueryDTO;
import cn.hfjava.kz.entity.dto.StudentWriteAppliDTO;
import cn.hfjava.kz.entity.po.Application;
import cn.hfjava.kz.entity.vo.*;
import cn.hfjava.kz.service.ApplicationService;
import cn.hfjava.kz.service.DocumentService;
import cn.hfjava.kz.service.StudentService;
import cn.hfjava.kz.service.TemplatesService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author Yinshijay
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/declare")
@Tag(name = "申报管理模块", description = "申报管理模块接口")
public class ApplicationController {
    private final ApplicationService applicationService;
    private final TemplatesService templateService;
    private final DocumentService documentService;
    private final StudentService studentService;

    @GetMapping("/list")
    @Operation(summary = "查询所有申报表信息", description = "查询所有申报表信息接口")
    public SaResult list() {
        List<Application> list = applicationService.list();
        return SaResult.data(list);
    }

    @DeleteMapping("/delete/{id}")
    @Operation(summary = "逻辑删除申报记录")
    public SaResult deleteDeclare(@PathVariable Integer id) {
        Application application = applicationService.getById(id);
        if (application == null || application.getDeleted() == 1) {
            return SaResult.error("申报记录不存在");
        }
        applicationService.removeById(id);
        return SaResult.ok("删除申报记录成功");
    }

    @DeleteMapping("/delete")
    @Operation(summary = "批量逻辑删除申报记录")
    public SaResult deleteDeclareBatch(@RequestBody List<Integer> ids) {
        applicationService.removeByIds(ids);
        return SaResult.ok("批量删除申报记录成功");
    }

    @Operation(summary = "修改申报记录")
    @PutMapping("/update")
    public SaResult updateDeclare(@Validated(UpdateGroup.class) @RequestBody ApplicationFormDTO applicationFormDto) {
        //该申报记录不存在，修改失败
        Application applicationEntity = new Application();
        //将前端传入的ApplicationDTO对象中的数据拷贝到Application持久对象
        BeanUtils.copyProperties(applicationFormDto, applicationEntity);
        applicationService.updateById(applicationEntity);
        return SaResult.ok("修改用户信息成功");
    }

    @Operation(summary = "分页查询申报记录")
    @PostMapping("/queryDeclare")
    public SaResult listPage(@RequestBody ApplicationQueryDTO applicationQueryDto) {
        PageVO<ApplicationVO> pageVO = applicationService.findByPage(applicationQueryDto);
        return SaResult.ok("查询成功").setData(pageVO);
    }


    @Operation(summary = "根据考生id查询出申报表没有的字段")
    @GetMapping("/get")
    public StudentAppliVO getData(@RequestParam Integer studentId) {
        return applicationService.getByStudentId(studentId);
    }

    @Operation(summary = "填写考生信息到申报表")
    @PostMapping("/save")
    public SaResult saveUser(@RequestBody StudentWriteAppliDTO studentWriteAppliDTO) {

        Application application = new Application();
        //将前端传来的数据拷贝到Application中
        BeanUtils.copyProperties(studentWriteAppliDTO, application);
        applicationService.saveApplication(application);
        return SaResult.ok("考生信息保存成功");
    }


@Operation(summary = "根据考生id导出docx")
@GetMapping("/generate/{studentId}")
public void generateDocx(HttpServletResponse response, @PathVariable Integer studentId, @RequestParam String temName) {
    // 获取需要填充的数据
    WordVO wordVO = applicationService.getWordData(studentId);
    if (wordVO == null) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        return;
    }

    // 转换 WordVO 为 fieldsMap
    Map<String, Object> fieldsMap = createFieldsMap(wordVO);

    // 获取头像的 URL 并添加到 fieldsMap 中
    String avatarUrl = getAvatarUrlByStudentId(studentId);
    if (avatarUrl != null) {
        fieldsMap.put("avatar", avatarUrl);
    }
    System.out.println("FieldsMap: " + fieldsMap);

    // 查询模板地址
    String temUrl = templateService.findTemplateAddressByName(temName);
    if (temUrl == null) {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    //根据studentId查询name
    String name = studentService.getById(studentId).getName();

    try (InputStream templateInputStream = new URL(temUrl).openStream();
         XWPFDocument doc = new XWPFDocument(templateInputStream)) {

        // 替换文档中的占位符
        replaceText(doc, fieldsMap);

        // 设置响应类型和文件名
        String encodedFileName = URLEncoder.encode(name+".docx", StandardCharsets.UTF_8.toString());
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);

        // 将文档写入响应输出流中
        try (OutputStream out = response.getOutputStream()) {
            doc.write(out);
        }
    } catch (IOException e) {
        e.printStackTrace();
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}

    private void replaceText(XWPFDocument doc, Map<String, Object> fieldsMap) {
        // 处理段落中的占位符
        for (XWPFParagraph paragraph : doc.getParagraphs()) {
            replaceTextInParagraph(paragraph, fieldsMap);
        }

        // 处理表格中的占位符
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        replaceTextInParagraph(paragraph, fieldsMap);
                    }
                }
            }
        }
    }

    private void insertImage(XWPFParagraph paragraph, byte[] imageBytes, String imageUrl) throws IOException, InvalidFormatException {
        XWPFRun run = paragraph.createRun();
        System.out.println("插入具有大小的图像: " + imageBytes.length + " bytes");
        String fileExtension = getFileExtension(imageUrl).toLowerCase();
        int imageType;

        switch (fileExtension) {
            case "jpg":
            case "jpeg":
                imageType = XWPFDocument.PICTURE_TYPE_JPEG;
                break;
            case "png":
                imageType = XWPFDocument.PICTURE_TYPE_PNG;
                break;
            default:
                throw new IOException("不支持的图像格式: " + fileExtension);
        }

        try (InputStream imageStream = new ByteArrayInputStream(imageBytes)) {
            run.addPicture(imageStream, imageType, "avatar." + fileExtension, Units.toEMU(80), Units.toEMU(100));
            System.out.println("插入成功");
        }
    }

    private void replaceTextInParagraph(XWPFParagraph paragraph, Map<String, Object> fieldsMap) {
        List<XWPFRun> runs = new ArrayList<>(paragraph.getRuns());
        for (XWPFRun run : runs) {
            String text = run.text();
            for (Map.Entry<String, Object> entry : fieldsMap.entrySet()) {
                String placeholder = "{" + entry.getKey() + "}";
                String replacement = entry.getValue() != null ? entry.getValue().toString() : "";

                if (text.contains(placeholder)) {
                    if ("avatar".equals(entry.getKey())) {
                        try {
                            String imageUrl = replacement;  // 直接使用原始 URL
                            byte[] imageBytes = downloadImage(imageUrl);  // 下载图片
                            insertImage(paragraph, imageBytes, imageUrl);  // 插入图片
                            run.setText("", 0); // 清除占位符文本
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else {
                        text = text.replace(placeholder, replacement);
                        run.setText(text, 0);
                    }
                }
            }
        }
    }


    private byte[] downloadImage(String imageUrl) throws IOException {
        System.out.println("Attempting to download image from URL: " + imageUrl);

        URL url = new URL(imageUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept", "image/jpeg,image/png");

        int responseCode = connection.getResponseCode();
        if (responseCode != HttpURLConnection.HTTP_OK) {
            throw new IOException("HTTP error code: " + responseCode);
        }

        try (InputStream in = connection.getInputStream();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
            byte[] imageBytes = out.toByteArray();
            System.out.println("图片下载，大小: " + imageBytes.length + " bytes");



            return imageBytes;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
    }



    private String getAvatarUrlByStudentId(Integer studentId) {
        return documentService.selectById(studentId);
    }

    private Map<String, Object> createFieldsMap(WordVO wordVO) {
        Map<String, Object> fieldsMap = new HashMap<>();
        fieldsMap.put("name", wordVO.getName());
        fieldsMap.put("gender", wordVO.getGender());
        fieldsMap.put("birthdate", wordVO.getBirthdate());
        fieldsMap.put("education", wordVO.getEducation());
        fieldsMap.put("identityId", wordVO.getIdentityId());
        fieldsMap.put("domicile", wordVO.getDomicile());
        fieldsMap.put("gradSchool", wordVO.getGradSchool());
        fieldsMap.put("major", wordVO.getMajor());
        fieldsMap.put("dipNum", wordVO.getDipNum());
        fieldsMap.put("gradDate", wordVO.getGradDate());
        fieldsMap.put("workUnit", wordVO.getWorkUnit());
        fieldsMap.put("phone", wordVO.getPhone());
        fieldsMap.put("aplPot", wordVO.getAplPot());
        fieldsMap.put("aplLevel", wordVO.getAplLevel());
        fieldsMap.put("prvCtf", wordVO.getPrvCtf());
        fieldsMap.put("ctfNum", wordVO.getCtfNum());
        fieldsMap.put("insCity", wordVO.getInsCity());
        fieldsMap.put("evaBatch", wordVO.getEvaBatch());
        fieldsMap.put("evaLocation", wordVO.getEvaLocation());
        fieldsMap.put("prmsState", wordVO.getPrmsState());
        fieldsMap.put("emplOp", wordVO.getEmplOp());
        return fieldsMap;
    }

    private String getFileExtension(String url) {
        String fileName = url.substring(url.lastIndexOf('/') + 1);
        return fileName.substring(fileName.lastIndexOf('.') + 1);
    }

//    private String replaceUrlPath(String url) throws UnsupportedEncodingException, MalformedURLException {
//        URL originalUrl = new URL(url);
//        String protocol = originalUrl.getProtocol();
//        String host = originalUrl.getHost();
//        int port = originalUrl.getPort();
//        String path = originalUrl.getPath();
//        String encodedPath = URLEncoder.encode(path, StandardCharsets.UTF_8.toString()).replaceAll("%2F", "/");
//        return protocol + "://" + host + (port != -1 ? ":" + port : "") + encodedPath;
//    }



    @Operation(summary = "根据考生id批量导出docx")
    @PostMapping("/generate/batch")
    public void generateBatchDocx(HttpServletResponse response, @RequestBody List<Integer> studentIds, @RequestParam String temName) {
        // 获取模板地址
        String temUrl = templateService.findTemplateAddressByName(temName);
        if (temUrl == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ZipOutputStream zos = new ZipOutputStream(baos)) {

            for (Integer studentId : studentIds) {
                // 获取需要填充的数据
                WordVO wordVO = applicationService.getWordData(studentId);
                if (wordVO == null) {
                    continue; // 如果某个学生的数据不存在，跳过该学生
                }

                // 转换 WordVO 为 fieldsMap
                Map<String, Object> fieldsMap = createFieldsMap(wordVO);

                // 获取头像的 URL 并添加到 fieldsMap 中
                String avatarUrl = getAvatarUrlByStudentId(studentId);
                if (avatarUrl != null) {
                    fieldsMap.put("avatar", avatarUrl);
                }

                try (InputStream templateInputStream = new URL(temUrl).openStream();
                     XWPFDocument doc = new XWPFDocument(templateInputStream)) {



                    //根据studentId查询name
                    String name = studentService.getById(studentId).getName();

                    // 替换文档中的占位符
                    replaceText(doc, fieldsMap);

                    // 将文档写入 Zip 文件中
                    ZipEntry entry = new ZipEntry(name + ".docx");  // 根据学生 ID 生成文件名
                    zos.putNextEntry(entry);
                    doc.write(zos);
                    zos.closeEntry();
                }
            }

            // 设置响应类型和文件名
            String encodedFileName = URLEncoder.encode("documents.zip", StandardCharsets.UTF_8.toString());
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);

            // 将 Zip 文件写入响应输出流中
            try (OutputStream out = response.getOutputStream()) {
                baos.writeTo(out);
            }
        } catch (IOException e) {
            e.printStackTrace();
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }
}